﻿//-------------------------------------------------------------------
//	Copyright (c) 2010-2014  Zhirnov Andrey
//	This file is part of the "UX Standard Lib" project.
//	See copyright notice in "UX_STL_Core.h".
//-------------------------------------------------------------------

#ifndef _UXS_ATOMIC_H
#define _UXS_ATOMIC_H

#pragma once

#include "../OS/Posix/AtomicOp.h"
#include "../OS/Windows/AtomicOp.h"

namespace UX_STL
{
namespace UXTypes
{
	
	//
	// Atomic
	//

	template <typename T>
	struct TAtomic
	{
	// types
	public:
		typedef T						value_t;
		typedef TAtomic<T>				Self;
		typedef _platform_::AtomicOp	Op;

	// variables
	private:
		volatile T			_iAtomic;

	// methods
	public:
		TAtomic (): _iAtomic(0) {}
		explicit TAtomic (T val): _iAtomic(val) {}
		explicit TAtomic (const Self &sObj): _iAtomic(sObj._iAtomic) {}

		operator const volatile T () const		{ return Get(); }

		Self &	operator ++ ()					{ Op::Inc<T>( _iAtomic );		  return *this; }
		Self &	operator -- ()					{ Op::Dec<T>( _iAtomic );		  return *this; }
		Self &	operator += (const T& right)	{ Op::Add<T>( _iAtomic, right );  return *this; }
		Self &	operator -= (const T& right)	{ Op::Sub<T>( _iAtomic, right );  return *this; }
		Self &	operator =  (const T& right)	{ Op::Set<T>( _iAtomic, right );  return *this; }
		Self &	operator |= (const T& right)	{ Op::Or<T> ( _iAtomic, right );  return *this; }
		Self &	operator &= (const T& right)	{ Op::And<T>( _iAtomic, right );  return *this; }
		Self &	operator ^= (const T& right)	{ Op::Xor<T>( _iAtomic, right );  return *this; }
		
		T		Inc ()							{ return Op::Inc<T>( _iAtomic ); }
		T		Dec ()							{ return Op::Dec<T>( _iAtomic ); }
		T		Get ()	const					{ return Op::Get<T>( _iAtomic ); }
		T		Add (const T& right)			{ return Op::Add<T>( _iAtomic, right ); }
		T		Sub (const T& right)			{ return Op::Sub<T>( _iAtomic, right ); }
		T		Set (const T& right)			{ return Op::Set<T>( _iAtomic, right ); }
		T		Or  (const T& right)			{ return Op::Or<T> ( _iAtomic, right ); }
		T		And (const T& right)			{ return Op::And<T>( _iAtomic, right ); }
		T		Zor (const T& right)			{ return Op::Xor<T>( _iAtomic, right ); }

		Self	operator ++ (int)
		{
			const Self  ret( _iAtomic );
			++(*this);
			return ret;
		}

		Self	operator -- (int)
		{
			const Self  ret( _iAtomic );
			--(*this);
			return ret;
		}


		// if *this == compare then *this = val return old *this
		T CompareEx (const T& val, const T& compare)
		{
			return Op::CmpEx<T>( _iAtomic, val, compare );
		}
	};


	typedef TAtomic< bool >			atomic_bool;

	typedef TAtomic< int8  >		atomic_int8;
	typedef TAtomic< int16 >		atomic_int16;
	typedef TAtomic< int32 >		atomic_int32;
	typedef TAtomic< int64 >		atomic_int64;
	typedef TAtomic< isize >		atomic_isize;

	typedef TAtomic< uint8  >		atomic_uint8;
	typedef TAtomic< uint16 >		atomic_uint16;
	typedef TAtomic< uint32 >		atomic_uint32;
	typedef TAtomic< uint64 >		atomic_uint64;
	typedef TAtomic< usize  >		atomic_usize;

//-------------------------------------------------------------------

}	// UXTypes
}	// UX_STL

#endif	//_UXS_ATOMIC_H